<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"
            "http://www.w3.org/TR/REC-html40/loose.dtd">
<HTML>
<HEAD>



<META http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<META name="GENERATOR" content="hevea 1.08">
<LINK rel="stylesheet" type="text/css" href="umsroot.css">
<TITLE>
Demon Predicates
</TITLE>
</HEAD>
<BODY >
<A HREF="umsroot112.html"><IMG SRC ="previous_motif.gif" ALT="Previous"></A>
<A HREF="umsroot104.html"><IMG SRC ="contents_motif.gif" ALT="Up"></A>
<A HREF="umsroot114.html"><IMG SRC ="next_motif.gif" ALT="Next"></A>
<HR>

<H2 CLASS="section"><A NAME="htoc252">17.9</A>&nbsp;&nbsp;Demon Predicates</H2>
<A NAME="secdemon"></A>A common pattern when implementing data-driven algorithms is the following
variant of the report/1 example from above:
<BLOCKQUOTE CLASS="quote"><PRE CLASS="verbatim">
report(X) :-
      suspend(report1(X), 1, X-&gt;constrained).      % suspend

report1(X) :-
        ( var(X) -&gt;
            writeln(constrained(X)),
            suspend(report(X), 1, X-&gt;constrained)  % re-suspend
        ;
            writeln(instantiated(X))               % die
        ).
</PRE></BLOCKQUOTE>
Here we have a goal that keeps monitoring changes to its variables.
To do so, it suspends on some or all of those variables.
When a change occurs, it gets woken, does something, and re-suspends.
The repeated re-suspending has two disadvantages: it can be inefficient,
and the goal does not have a unique identifying suspension that could be
easily referred to, because on every re-suspend a new suspension is created.<BR>
<BR>
To better support this type of goals, ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP> provides a special type
of predicate, called a <B>demon</B>. A predicate is turned into a
<A NAME="@default1032"></A>
demon by annotating it with a
<A HREF="../bips/kernel/compiler/demon-1.html"><B>demon/1</B></A><A NAME="@default1033"></A>
declaration.
A demon goal differs from a normal goal only in its behaviour on
waking. While a normal goal disappears from the resolvent when it is
woken, the demon remains in the resolvent.
Declaratively, this corresponds to an implicit recursive call in
the body of each demon clause.
Or, in other words, the demon goal forks into one goal that remains in the
suspended part of the resolvent, and an identical one
that gets scheduled for execution.<BR>
<BR>
With this functionality, our above example can be done more
efficiently. One complication arises, however. Since the goal
implicitly re-suspends, it now has to be explicitly killed when
it is no longer needed. The easiest way to achieve this is to
let it remember its own suspension in one of its arguments.
This can then be used to kill the suspension when required:
<BLOCKQUOTE CLASS="quote"><PRE CLASS="verbatim">
% A demon that wakes whenever X becomes more constrained
report(X) :-
      suspend(report(X, Susp), 1, X-&gt;constrained, Susp).

:- demon(report/2).
report(X, Susp) :-
      ( var(X) -&gt;
          writeln(constrained(X))   % implicitly re-suspend
      ;
          writeln(instantiated(X)),
          kill_suspension(Susp)     % remove from the resolvent
      ).
</PRE></BLOCKQUOTE>
<HR>
<A HREF="umsroot112.html"><IMG SRC ="previous_motif.gif" ALT="Previous"></A>
<A HREF="umsroot104.html"><IMG SRC ="contents_motif.gif" ALT="Up"></A>
<A HREF="umsroot114.html"><IMG SRC ="next_motif.gif" ALT="Next"></A>
</BODY>
</HTML>
